#include <osa.h> 
#include <service/osa_bsem.h>
#include <service/osa_dtimer.h>
#include "ports.h"
#include "Config.h"
#include "task_keyboard.h"

OST_DTIMER timer_pin;
OST_DTIMER timer_pin_2;

t_port port;

BOOL Key_changed;
BOOL Key_pressed;

#define PRESS_MSEC    150   // Stable time before registering pressed
#define RELEASE_MSEC  200  // Stable time before registering released
#define TIMER_CONST 100

OST_FLAG8   F_Button;


void task_keyboard(void) {


    INPUT_PIN_1_TRIS = 1;
    INPUT_PIN_1_TRIS = 1;

    /*FIXME move in Config.h*/
    /*Interupt on change enabled*/
    CNEN1bits.CN11IE = 1;
    CNEN1bits.CN12IE = 1;
    /*Pullups enabled on change enabled*/
    /*
    CNPU1bits.CN11PUE = 1;
    CNPU1bits.CN12PUE = 1;
    */
    IPC4bits.CNIP = 7; // set IP as 7
    IFS1bits.CNIF = 0; // clear the interrupt flag
    IEC1bits.CNIE = 1; // enable the interrupt on change notification

    OS_Dtimer_Create(timer_pin);
    OS_Dtimer_Run(timer_pin, 1);

    while (1) {
        OS_Bsem_Wait(BS_BUTTON_CN); //pressed
        if ((port.status.pin_1 == CHANGED) && port.value.pin_1) {
	        	OS_Dtimer_Run(timer_pin, PRESS_MSEC / TIMER_CONST);
	        	OS_Dtimer_Wait(timer_pin);
	        	if (INPUT_PIN_1_READ == 0) {
		        	port.status.pin_1 = UNCHANGED;
		        	port.value.pin_1 = 0;
					}
					
					else {
						OS_Flag_Set_1(F_Button, BUTTON_1);
					}
	        
        }

    }
    OS_Yield();
}

// change notification interrupt service routine
void DebounceSwitch1(void);

void __attribute__ ((__interrupt__, auto_psv))_CNInterrupt(void) {

 
    char temp;
    temp = OS_DI();

    port.value.pin_1 =  INPUT_PIN_1_READ;
    port.status.pin_1 =  CHANGED;
    OS_Bsem_Set(BS_BUTTON_CN);
    IFS1bits.CNIF = 0; // clear the interrupt flag
    OS_DI(temp);
}



// This function reads the key state from the hardware.
#define RawKeyPressed INPUT_PIN_1_READ;

// This holds the debounced state of the key.
char DebouncedKeyPress = FALSE;

//   Service routine called every CHECK_MSEC to
// debounce both edges

void DebounceSwitch1(void) {
    OS_Dtimer_Run(timer_pin, RELEASE_MSEC / TIMER_CONST);
    char RawState;
    Key_changed = FALSE;
    Key_pressed = DebouncedKeyPress;
    RawState = RawKeyPressed;
    if (RawState == DebouncedKeyPress) {
        // Set the timer which allows a change from current state.
        if (DebouncedKeyPress) {
        	OS_Dtimer_Run(timer_pin, RELEASE_MSEC / TIMER_CONST);}
        else {
        	OS_Dtimer_Run(timer_pin, PRESS_MSEC / TIMER_CONST);}
    } else {
        // Key has changed - wait for new state to become stable.
        if (OS_Dtimer_Check(timer_pin)) {
            // Timer expired - accept the change.
            DebouncedKeyPress = RawState;
            Key_changed = TRUE;
            Key_pressed = DebouncedKeyPress;
            // And reset the timer.
            if (DebouncedKeyPress) {OS_Dtimer_Run(timer_pin, RELEASE_MSEC / TIMER_CONST);}
            else {OS_Dtimer_Run(timer_pin, PRESS_MSEC / TIMER_CONST);}
        }
    }
}


